package com.league.blog.controller;

import com.league.blog.pojo.ArticleWithBLOBs;
import com.league.blog.pojo.User;
import com.league.blog.service.ArticleService;
import com.league.blog.system.Config;
import com.league.blog.system.redis.RedisUtils;
import com.league.blog.system.shiro.ShiroUtils;
import com.league.blog.utils.DataUtils;
import com.league.blog.utils.FileUtils;
import com.league.blog.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author 黄豪琦
 * 日期:2020-03-30 15:17
 * 说明:
 */
@Controller
@RequestMapping("/editor")
@Slf4j
public class EditorController {

    @Value("${images.path}")
    String uploadedFolder;

    private RedisUtils redisUtils;

    @Autowired
    public void setRedisUtils(RedisUtils redisUtils) {
        this.redisUtils = redisUtils;
    }

    private ArticleService articleService;

    @Autowired
    public void setArticleService(ArticleService articleService) {
        this.articleService = articleService;
    }

    @RequestMapping("")
    public String writeArticle(String articleCode, HttpServletRequest request, Model model) {
        ArticleWithBLOBs article;
        User user = (User) SecurityUtils.getSubject().getPrincipal();
        if (StringUtils.isBlank(articleCode)) {
            //尝试从缓存中取
            if ((article = (ArticleWithBLOBs) redisUtils.get(Config.getSaveInRealTimeKey() + user.getAccountName())) != null) {
                model.addAttribute("article", article);
            }
        } else {
            //查询数据库 是否有这个文章 如果有则比对用户id
            if ((article = articleService.findArticleByCode(articleCode)) != null) {
                if (article.getUserId().equals(user.getUserId())) {
                    model.addAttribute("article", article);
                } else {
                    return "redirect:/editor";
                }
            } else {
                return "redirect:/editor";
            }
        }
        return "editor";
    }

    /**
     * 文章上传图片
     *
     * @param file
     * @return
     */
    @RequestMapping("/upload/img")
    @ResponseBody
    public Map<String, Object> uploadImg(@RequestParam(value = "editormd-image-file", required = false) MultipartFile file,
                                         HttpServletRequest request) {
        Map<String, Object> resultMap = new HashMap<String, Object>();
        String suffix = FileUtils.getFileType(file.getOriginalFilename());
        String fileName = FileUtils.createFileName("img", suffix);
        User user = (User) SecurityUtils.getSubject().getPrincipal();
        //保存
        try {
            byte[] bytes = file.getBytes();
            Path path = Paths.get(uploadedFolder + fileName);
            Files.write(path, bytes);
            //保存此博客在编辑时用到的图片
            ArticleWithBLOBs article = (ArticleWithBLOBs) redisUtils.get(Config.getSaveInRealTimeKey() + user.getAccountName());
            if (article == null) {
                article = new ArticleWithBLOBs();
                article.setUserId(user.getUserId());
            }
            article.addImages(fileName);
            redisUtils.put(Config.getSaveInRealTimeKey() + user.getAccountName(), article);
            resultMap.put("success", 1);
            resultMap.put("message", "上传成功！");
            resultMap.put("url", "/img/" + fileName);
        } catch (Exception e) {
            resultMap.put("success", 0);
            resultMap.put("message", "上传失败！");
            e.printStackTrace();
        }
        return resultMap;
    }

    @RequestMapping("/submit")
    @ResponseBody
    public Map<String, Object> submitArticle(HttpServletRequest request, ArticleWithBLOBs article) {
        Map<String, Object> resultMap = new HashMap<String, Object>();
        User user = (User) SecurityUtils.getSubject().getPrincipal();
        if (null != article && null != article.getArticleTitle()) {
            try {
                if (null == article.getArticleCode()) {
                    article.setArticleCode(StringUtils.getRandomStr(5));
                }
                if (null == article.getCreateTime()) {
                    article.setCreateTime(DataUtils.getCurrentDate());
                }
                article.setEditorTime(DataUtils.getCurrentDate());
                article.setUserId(user.getUserId());
                //数据库操作
                articleService.saveArticle(article);
                resultMap.put("code", 1);
                resultMap.put("message", "发布成功");
                resultMap.put("articleCode", article.getArticleCode());
                //清理冗余 清理redis中的缓存

                cleanUpRedundantPictures(user.getAccountName());
                redisUtils.delete(Config.getSaveInRealTimeKey() + user.getAccountName());
            } catch (Exception ex) {
                log.error(ex.getMessage());
                ex.printStackTrace();
                resultMap.put("code", 2);
                resultMap.put("message", "发布失败");
                resultMap.put("body", "发生内部错误,请联系网站管理员");
            }
        } else {
            resultMap.put("code", 2);
            resultMap.put("message", "发布失败");
            resultMap.put("body", "系统没有接收到你的文章或文章标题为空");
        }
        return resultMap;
    }

    @RequestMapping("/realtime")
    @ResponseBody
    public Map saveArticlesInRealTime(ArticleWithBLOBs article){
        Map<String, Object> result = new HashMap<>();
        try {
            if (article != null && article.getArticleTitle() != null) {
                User user = ShiroUtils.getUser();
                ArticleWithBLOBs redisArticle = (ArticleWithBLOBs) redisUtils.get(Config.getSaveInRealTimeKey() + user.getAccountName());
                if (redisArticle == null) {
                    redisArticle = new ArticleWithBLOBs();
                }
                redisArticle.update(article);
                redisUtils.put(Config.getSaveInRealTimeKey() + user.getAccountName(), redisArticle);
                result.put("code", 1);
            }
        } catch (Exception e) {
            log.error("文章实时保存出错："+e.getMessage());
            e.printStackTrace();
            result.put("code", 2);
        }
        return result;
    }

    /**
     * 清理冗余图片
     */
    private void cleanUpRedundantPictures(String userAccount) {
        ArticleWithBLOBs article = (ArticleWithBLOBs) redisUtils.get(Config.getSaveInRealTimeKey() + userAccount);
        final List<String> images;
        try {
            if ((images = article.getImages()) != null && images.size() > 0) {
                int successCount = 0;
                int failCount = 0;
                int count = 0;
                for (String item : images) {
                    try {
                        if (!article.getArticleContent().contains(item)) {
                            File file = new File(uploadedFolder + item);
                            count++;
                            if (file.delete()) {
                                successCount++;
                            } else {
                                failCount++;
                            }
                        }
                    } catch (Exception e) {
                        log.info("删除冗余图片出错，图片名：" + item + "\t信息：" + e.getMessage());
                        failCount++;
                    }
                }
                log.info("文章[" + article.getArticleTitle() + "]中有"
                        + count + "张冗余图片，已删除" + successCount + "张，删除失败" + failCount + "次");
            }
        } catch (NullPointerException e) {
            log.error("发生了空指针，但是不要紧");
        }
    }
}
